package com.hyy.asm.protocol;

import com.hyy.asm.config.Config;
import com.hyy.asm.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 必须和 LengthFieldBasedFrameDecoder 一起使用，确保接到的ByteBuf消息是完整的
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf,Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out = ctx.alloc().buffer();
        //1、4 字节的魔数
        out.writeBytes(new byte[]{1,2,3,4});
        //2、1 字节的版本
        out.writeByte(1);
        //3、1 字节的序列化方式 0 jdk 1 json
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        //4、1 字节的指令类型
        out.writeByte(msg.getMessageType());
        //5、4 字节的指令序号
        out.writeInt(msg.getSequenceId());
        out.writeByte(0xff);
        //6、获取字节数组
//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
//        ObjectOutputStream oos = new ObjectOutputStream(baos);
//        oos.writeObject(msg);
//        byte[] bytes = baos.toByteArray();
        byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);
        //7、4 字节的长度
        out.writeInt(bytes.length);
        //8、内容
        out.writeBytes(bytes);
        outList.add(out);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magicNum = in.readInt();
        byte version =in.readByte();
        byte serializerType =in.readByte();
        byte messageType = in.readByte();
        int sequenceId =in.readInt();
        in.readByte();
        int length = in.readInt();
        byte[] bytes = new byte[length];
        in.readBytes(bytes, 0,length);
//        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
//        Message message =(Message) ois.readObject();
        Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializerType];
        Class<?> messageClass = Message.getMessageClass(messageType);
        Object message = algorithm.deserialize(messageClass, bytes);

        log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
        log.debug("{}",message);
        out.add(message);
    }

}
